home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / lib / tex / docsty.shar / docsty.c next >
C/C++ Source or Header  |  1988-04-18  |  6KB  |  229 lines

  1. /*
  2.  * DOCSTY.C
  3.  *
  4.  * Convert TeX DOC files to TeX STY files for faster loading.  The input
  5.  * file must obey the following rules:
  6.  *
  7.  *    % is the comment character;
  8.  *    \ is the escape character;
  9.  *    Does not depend on RETURN RETURN producing a \par;
  10.  *    Ends with a final newline, or can have one added.
  11.  *    Works if the characters SPACE, TAB (^^I), LINEFEED (^^J), VERTICAL TAB
  12.  *        (^^K), FORMFEED (^^L), and RETURN (^^M) are all to be treated
  13.  *        as spaces; in fact, they are CONVERTED to spaces (except after
  14.  *        a \).
  15.  *    Works if all the SPACE characters are converted to newlines.
  16.  *
  17.  * The first two of these are equivalent to the definitions in PLAIN.  The
  18.  * last is NOT:  PLAIN makes ^^L active, translating into \par; ^^K as the
  19.  * superscript character, and so on.  However, such uses are not needed in
  20.  * a DOC file.  DOCSTY does NOT translate the "^^" forms to the actual
  21.  * characters; it reacts only to the actual control characters.  So while
  22.  * you can't have a FORMFEED in the input, you CAN have the three-character
  23.  * sequence ^^L, which TeX will translate into a FORMFEED.  Note that you
  24.  * can get around the last condition - which mainly shows up in a context in
  25.  * which you've made SPACE an active character and are doing something like
  26.  * \def {...something...} - by using ^^` in place of SPACE.
  27.  * 
  28.  * DOCSTY will try to keep its output lines short, but it will only break
  29.  * a line at a space.  If an input line is very long but contains no space,
  30.  * the output will contain a very long line, too.
  31.  */
  32.  
  33. /*
  34.  *  Tony Li (tli%sargas.usc.edu@oberon.USC.EDU)
  35.  *  5/22/86
  36.  *
  37.  * Copyright (c) 1986
  38.  * University of Southern California
  39.  */
  40.  
  41. /*
  42.  * Modified, 6-Nov-87, by Jerry Leichter (LEICHTER-JERRY@CS.YALE.EDU)
  43.  *    \% doesn't mark the beginning of a comment; in fact, in general, the
  44.  *    character just after \ should be left alone.  Break ONLY at spaces;
  45.  *    previous version would force a line out if it got too long, producing
  46.  *    an extra linefeed.  This was aggravated by the fact that the newline
  47.  *    after a comment was retained.
  48.  * Modified, 30-Jan-88, by Jerry Leichter
  49.  *    TeX always discards leading space after a newline, even if a "%" came
  50.  *    first.  We have to do the same.  (Problem found by Steve Cochran,
  51.  *    <cochran%brand.usc.edu@oberon.usc.edu>.)
  52.  */
  53.  
  54. #include <stdio.h>
  55. #include <ctype.h>
  56. #define STRLEN    256
  57. #define WHITE    1
  58. #define BLACK    2
  59. #define COMMENT    '%'
  60. #define BACK    '\\'
  61. #define SP    ' '
  62. #define NL    '\n'
  63. #define CR    '\r'
  64. #define EOS    '\0'
  65. #define THRESH    78
  66.  
  67. #ifdef vms
  68. #define FAIL    0
  69. #else
  70. #define FAIL    1
  71. #endif
  72.  
  73. /*
  74.  * dumpline() ensures that there is room for at least two characters in
  75.  * the output buffer.  Hence, SAVECHAR can be called twice between calls
  76.  * to TESTBUF.
  77.  */
  78. #define SAVECHAR    {buf[linelen++] = ch;}
  79. #define TESTBUF        {if (linelen >= THRESH) dumpline(out);}
  80.  
  81. char    buf[STRLEN];    /* Output buffer        */
  82. int    linelen = 0;    /* Length of output line so far    */
  83. int    linenum = 1;    /* Input line number        */
  84.  
  85. main(argc, argv)
  86. int    argc;
  87. char    *argv[];
  88. {    char    dest[STRLEN];
  89.     FILE    *in;
  90.     FILE    *out;
  91.     int    state;
  92.     int    ret;
  93.     char    ch;
  94.  
  95.     if (argc != 2)
  96.     {    fprintf(stderr,"Usage:  docsty <file-name>\n");
  97.         exit(FAIL);
  98.     }
  99.     strcpy(dest,argv[1]);
  100.     strcat(argv[1],".doc");
  101.     strcat(dest,".sty");
  102.     if ((in = fopen(argv[1],"r")) == NULL)
  103.     {    perror("Can't open input file");
  104.         exit(FAIL);
  105.     }
  106. #ifdef vms
  107.     out = fopen(dest,"w","rfm=var","rat=cr");
  108. #else
  109.     out = fopen(dest,"w");
  110. #endif
  111.     if (out == NULL)
  112.     {    perror("Can't open output file");
  113.         exit(FAIL);
  114.     }
  115.  
  116.     state = WHITE;
  117.     while ((ch = getc(in)) != EOF)
  118.         {    if (ch == COMMENT)
  119.         {    /*
  120.              * Scan to end of line
  121.              */
  122.             while ((ch = getc(in)) != EOF && ch != NL)
  123.                 ;
  124.             if (ch == EOF)
  125.                 break;
  126.             linenum++;
  127.             /*
  128.              * Scan over leading whitespace on line, if any
  129.              */
  130.             while ((ch = getc(in)) != EOF && isspace(ch))
  131.                 if (ch == NL)
  132.                     break;
  133.             /*
  134.              * Re-scan beyond splice point
  135.              */
  136.             ungetc(ch,in);
  137.             continue;
  138.         }
  139.         else if (ch == BACK)
  140.         {    TESTBUF;
  141.             SAVECHAR;
  142.             if ((ch = getc(in)) == EOF)
  143.                 break;
  144.             if (ch == NL)
  145.                 linenum++;
  146.             SAVECHAR;
  147.             state = BLACK;
  148.         }
  149.         else if (isspace(ch))
  150.         {   if (ch == NL)
  151.             linenum++;
  152.             if (state == BLACK)        /* No space yet        */
  153.             {    ch = SP;
  154.             TESTBUF;        /* put it out        */
  155.             SAVECHAR;        /* and append a space    */
  156.             state = WHITE;        /* we've seen a space    */
  157.             }
  158.         }                /* otherwise, ignore    */
  159.         else                /* other char        */
  160.         {   TESTBUF;
  161.             SAVECHAR;            /* save it        */
  162.             state = BLACK;        /* we saw it        */
  163.         }
  164.     };
  165.     emptybuf(out);
  166.     fclose(in);
  167.     fclose(out);
  168. }
  169.  
  170. /*
  171.  * Dump the buffer.
  172.  *
  173.  * We break ONLY at a space.  If no SPACE can be found in the line so far,
  174.  * we do nothing; the next call will try again.  If the line buffer overflows,
  175.  * we complain right here.
  176.  *
  177.  * The surrounding code may assume that, on return, there is room for at
  178.  * least two more characters in buf.
  179.  */
  180. dumpline(out)
  181. FILE    *out;
  182. {    char    *pt;
  183.     char    *tt;
  184.  
  185.     tt = pt = &buf[linelen-1];
  186.     while (pt >= buf && *pt != SP)
  187.         pt--;
  188.     if (pt >= buf)
  189.     {    *pt++ = EOS;        /* Terminate at space        */
  190.         fputs(buf,out);        /* Put line out            */
  191.         fputc(NL,out);        /* Terminate it            */
  192.         if (strlen(buf) > THRESH)
  193.         {    printf(
  194. "Warning:  Line longer than %d characters generated; near input line %d.\n",
  195.             THRESH,linenum);
  196.         }
  197.         /*
  198.          * Copy the remaining characters to the beginning of the
  199.          * buffer, re-computing linelen in the process.
  200.          */
  201.         linelen = 0;
  202.         while (pt <= tt)
  203.             buf[linelen++] = *pt++;
  204.     }
  205.     else if (linelen >= sizeof(buf) - 2)
  206.     {    fprintf(stderr,
  207. "Too many input characters without a space; near input line %d.\n",
  208.             linenum);
  209.         exit(FAIL);
  210.     }
  211. }
  212.  
  213. /*
  214.  * Clear the buffer.  Normally, the last character of the input file was a
  215.  * newline, so dumpline() will be able to write the line out immmediately;
  216.  * but if not, we tack on a SPACE.
  217.  */
  218. emptybuf(out)
  219. FILE    *out;
  220. {    char    ch;
  221.  
  222.     dumpline(out);
  223.     if (linelen != 0)
  224.     {    ch = SP;
  225.         SAVECHAR;
  226.         dumpline(out);
  227.     }
  228. }
  229.